#5704d67e388a5517d33dc9ee23dba25a

import smtplib
import imaplib
import email
from email.mime.text import MIMEText
from email.header import Header, decode_header  # 添加 decode_header 导入
from email.utils import parsedate_to_datetime
import time
import configparser
import os
from sys import exit
import logging
import re
import traceback  # 添加导入

# 修改日志配置，添加文件模式和控制台模式
#logging.basicConfig() - Python标准库中的函数，用于配置日志系统的基本设置。
#如果autoemail.log文件不存在，Python的logging.FileHandler会自动创建这个文件
logging.basicConfig(
    level=logging.DEBUG,    #设置日志级别为DEBUG，这意味着会记录所有级别的日志信息（DEBUG、INFO、WARNING、ERROR、CRITICAL）
    format="%(asctime)s - %(levelname)s - %(message)s",
    handlers=[
        logging.FileHandler("autoemail.log", encoding="utf-8"),  # - 文件处理器，将日志写入到"autoemail.log"文件中，明确指定编码
        logging.StreamHandler()  # - 流处理器，将日志输出到控制台（终端）
    ]
)

# ====================== 加载配置文件 ======================
def load_config():
    """
    加载配置文件中的敏感信息
    :return: 配置字典   
    这个函数在文件开头被调用，用于加载邮件服务器的配置信息。
    """
    config = configparser.ConfigParser()
    config_path = os.path.join(os.path.dirname(__file__), "config.ini")
    
    if not os.path.exists(config_path):
        raise FileNotFoundError("配置文件 config.ini 未找到，请检查路径。")
    
    config.read(config_path)
    return {
        "SMTP_SERVER": config.get("email", "smtp_server"),
        "SMTP_PORT": config.getint("email", "smtp_port"),
        "IMAP_SERVER": config.get("email", "imap_server"),
        "IMAP_PORT": config.getint("email", "imap_port"),
        "SENDER_EMAIL": config.get("email", "sender_email"),
        "SENDER_PASSWORD": config.get("email", "sender_password"),
    }

# 加载配置
try:
    CONFIG = load_config()
except Exception as e:
    print(f"加载配置文件时出错: {e}")
    exit(1)

# ====================== 业务配置 ======================
# 授权关键字列表（用于匹配邮件标题或正文）
AUTHORIZATION_KEYWORDS = ["授权"]
# 需要处理的厂家邮箱列表（仅回复这些发件人的邮件）
AUTHORIZED_VENDORS = ["authcenter@huawei.com",
                      "netcarereport@huawei.com", 
                      "shenzhiqiang8@huawei-partners.com", 
                      "liu.wei101@zte.com.cn", 
                      "zhu.junqiang1@zte.com.cn", 
                      "shao.bin2@zte.com.cn", 
                      "li.fei30@zte.com.cn", 
                      "feng.qinhao@zte.com.cn", 
                      "wang.kun22@zte.com.cn", 
                      "yang.zhentao@zte.com.cn",
                      "chenle@xfusion.com", 
                      "zhangguoxuan@xfusion-partner.com", 
                      "SP.zhuhuanping@h3c.com",
                      "bai.xin@h3c.com", 
                      "gaoqiang@ieisystem-service.com", 
                      "sunjielong@onlinebj.com",
                      "zhu.hp@scsloan.net",
                      "yuxin49@huawei-partners.com", 
                      "liyu102@huawei.com", 
                      "zhaoshanghao@huawei.com",
                      "liuzihui7@huawei-partners.com",
                      "wangzuowei2@huawei-partners.com", 
                      "heyongding1@huawei-partners.com",
                      "huangqiaotong@huawei.com" 
                      ]
# 预先设置的抄送人名单（仅允许这些抄送人）
CC_WHITELIST = ["zhangzihao17@huawei-partners.com", 
                "yuxin49@huawei-partners.com", 
                "liyu102@huawei.com", 
                "liuzihui7@huawei-partners.com", 
                "shenzhiqiang8@huawei-partners.com", 
                "wangtao525@huawei-partners.com", 
                "zhaoshanghao@huawei.com", 
                "huangqiaotong@huawei.com", 
                "wangzuowei2@huawei-partners.com", 
                "heyongding1@huawei-partners.com",
                "gaodong14@huawei-partners.com",
                "sxlibo@sn.chinamobile.com"
                ]

# 在文件开头添加全局变量
PROCESSED_EMAILS_FILE = "processed_emails.txt"

def load_processed_emails():
    """加载已处理的邮件 Message-ID"""
    if not os.path.exists(PROCESSED_EMAILS_FILE):
        return set()
    with open(PROCESSED_EMAILS_FILE, "r", encoding="utf-8") as f:
        return set(line.strip() for line in f if line.strip())

def save_processed_email(message_id):
    """保存已处理的邮件 Message-ID"""
    with open(PROCESSED_EMAILS_FILE, "a", encoding="utf-8") as f:
        f.write(message_id + "\n")

# ====================== 功能函数 ======================
def extract_email(full_email):
    """
    从带名称的邮箱字符串中提取纯邮箱地址（如 "Name <email@example.com>" → "email@example.com"）
    """
    if not full_email:
        return ""
    match = re.search(r'<(.+?)>', full_email)
    return match.group(1) if match else full_email

def is_authorization_email(subject, body, from_email, cc_emails=None):
    """
    判断是否为需要回复的授权邮件
    :param cc_emails: 可以是列表或逗号分隔的字符串（如 "a@x.com, b@y.com"）
    """
    if cc_emails is None:
        cc_emails = []

    # 检查标题是否包含"回复"（不区分大小写）
    subject_lower = subject.lower()
    if "回复" in subject_lower :
        print(f"Debug - 邮件标题包含'回复'，跳过处理: {subject}")
        return False

    # 提取发件人纯邮箱地址
    from_email_clean = extract_email(from_email)
    print(f"Debug - 发件人原始: {from_email}, 提取后: {from_email_clean}")

    #  # 清理抄送人列表
    cc_emails_clean = []
    for email in cc_emails:
        if isinstance(email, str):
            cleaned = extract_email(email.strip('"'))
            # 检查清理后的邮箱地址是否有效:
            # 1. cleaned 不为空
            # 2. 包含"@"符号（基本邮箱格式验证）
            if cleaned and "@" in cleaned:
                # 将有效的邮箱地址添加到清理后的抄送人列表
                cc_emails_clean.append(cleaned)
    # 记录调试信息：打印最终清理后的抄送人列表
    logging.debug(f"抄送人: {cc_emails_clean}")

    # 调试：打印清理后的 cc_emails_clean
    print(f"Debug - cc_emails_clean: {cc_emails_clean}, type: {type(cc_emails_clean)}")

    # 检查是否包含目标邮箱
    target_email = "sxlibo@sn.chinamobile.com"
    if target_email in cc_emails_clean:
        print(f"Debug - 跳过邮件，因抄送人包含: {target_email}")
        return False

    # 其余逻辑（发件人检查、关键字检查等）
    ##1.检查发件人是否为授权厂家邮箱（使用提取后的纯邮箱）
    if from_email_clean not in AUTHORIZED_VENDORS:
        print(f"Debug - 发件人 {from_email_clean} 不在授权列表中")
        return False
    
    ##2.检查发件人是否为华为授权中心且邮件有抄送人
    if (from_email_clean == "authcenter@huawei.com" or from_email_clean == "netcarereport@huawei.com") and cc_emails:
        # 验证所有抄送人是否都在白名单中
        #if not all(email in CC_WHITELIST for email in cc_emails_clean):
            #return False
        # 验证至少有一人的邮箱在抄送人列表里20250715
        if any(email in CC_WHITELIST for email in cc_emails_clean):
            return True

    ##3.检查标题或内容是否包含授权关键字"授权"
    subject_lower = subject.lower()  
    #body_lower = body.lower()
    
    # 如果授权关键字列表为空，直接返回False
    if not AUTHORIZATION_KEYWORDS:
        return False
        
    # 遍历授权关键词列表中的每个关键词
    for keyword in AUTHORIZATION_KEYWORDS:
        # 检查当前关键词是否出现在邮件标题中（不区分大小写）
        # 注释说明：这里只检查标题，如果需要同时检查正文内容，可以取消下面被注释的代码
        # if keyword.lower() in subject_lower or keyword.lower() in body_lower:
        if keyword.lower() in subject_lower:
            return True  # 如果找到匹配的关键词，立即返回True
    return False  # 如果遍历完所有关键词都没有匹配，返回False

def send_reply_email(subject, to_email, original_body, original_headers, cc_emails=None):
    """
    发送自动回复邮件，并包含原邮件信息和签名
    """
    # 回复主题直接使用解码后的原主题（不再编码）
    reply_subject = "Re: " + original_headers["Subject"]  # 直接使用已解码的主题

    # 构建回复内容
    reply_body = (
        "同意\n\n"
        "---------------------------------\n"
        "sxlibo@sn.chinamobile.com\n"
        "陕西移动网管中心云平台维护室 李波\n"
        "TEL：13571822791\n\n"
        "AI邮件系统自动回复\n"
        "---------------------------------\n"
        "---------- 原邮件信息 ----------\n"
        f"发件人: {original_headers.get('From', '')}\n"
        f"发送时间: {original_headers.get('Date', '')}\n"
        f"收件人: {original_headers.get('To', '')}\n"
    )
    
    # 添加抄送信息（如果有）
    if original_headers.get('Cc'):
        reply_body += f"抄送: {original_headers.get('Cc', '')}\n"
    
    # 添加原邮件主题和正文
    reply_body += (
        f"主题: {original_headers.get('Subject', '')}\n\n"
        "---------- 原邮件内容 ----------\n"
        "> " + original_body.replace("\n", "\n> ")
    )

    # 构建邮件消息
    msg = MIMEText(reply_body, "plain", "utf-8")
    msg["Subject"] = Header(reply_subject, "utf-8").encode()  # 使用 encode() 方法
    msg["From"] = CONFIG["SENDER_EMAIL"]
    msg["To"] = to_email
    if cc_emails:
        msg["Cc"] = "; ".join(cc_emails)

    # 发送邮件
    try:
        with smtplib.SMTP_SSL(CONFIG["SMTP_SERVER"], CONFIG["SMTP_PORT"]) as server:
            server.login(CONFIG["SENDER_EMAIL"], CONFIG["SENDER_PASSWORD"])
            server.sendmail(CONFIG["SENDER_EMAIL"], [to_email] + (cc_emails or []), msg.as_string())
        print("自动回复邮件已发送。")
    except Exception as e:
        print(f"发送邮件时出错: {e}")

def process_email(subject, body, from_email, cc_emails=None, original_headers=None):
    """
    处理邮件并决定是否回复
    :param subject: 邮件标题
    :param body: 邮件内容
    :param from_email: 发件人邮箱
    :param cc_emails: 抄送人邮箱列表
    :param original_headers: 原邮件的头信息（字典格式，包含 From/To/Date/Subject/Cc）
    """
    if is_authorization_email(subject, body, from_email, cc_emails or []):
        send_reply_email(subject, from_email, body, original_headers or {}, cc_emails)
    else:
        print("非授权邮件，忽略。")

def fetch_emails(mail):
    """
    处理新邮件
    :param mail: 已建立的IMAP连接对象
    """
    processed_emails = load_processed_emails()  # 查询已处理的邮件列表
    try:
        mail.select("inbox")
        status, messages = mail.search(None, "UNSEEN")
        if status != "OK":
            print("未找到新邮件。")
            return

        for num in messages[0].split():
            status, data = mail.fetch(num, "(RFC822)")
            if status != "OK":
                continue

            msg = email.message_from_bytes(data[0][1])
            message_id = msg.get("Message-ID", "").strip()
            if message_id in processed_emails:
                print(f"邮件已处理，跳过 - Message-ID: {message_id}")
                continue

            # 解码主题（处理多段MIME编码）
            subject = ""
            for part, encoding in decode_header(msg.get("Subject", "")):  # 使用直接导入的 decode_header
                if isinstance(part, bytes):
                    subject += part.decode(encoding if encoding else "utf-8")
                else:
                    subject += part

            # 提取其他头信息（From/To/Date等）
            original_headers = {
                "From": msg.get("From", ""),
                "Date": msg.get("Date", ""),
                "To": msg.get("To", ""),
                "Subject": subject,  # 使用解码后的主题
                "Cc": msg.get("Cc", ""),
            }

            # 提取发件人邮箱（从 "Name <email>" 中提取纯邮箱）
            from_header = msg.get("From", "")
            if "<" in from_header and ">" in from_header:
                from_email = from_header.split("<")[-1].split(">")[0].strip()
            else:
                from_email = from_header.strip()

            cc_emails = []
            # 修复可能为 None 的情况
            cc_header = msg.get("Cc")
            if cc_header:
                cc_emails = [email.strip() for email in cc_header.split(",")]
            
            # 解析邮件正文
            body = ""
            if msg.is_multipart():
                for part in msg.walk():
                    if part.get_content_type() == "text/plain":
                        payload = part.get_payload(decode=True)
                        if isinstance(payload, bytes):
                            body = payload.decode("utf-8", errors="ignore")
                        else:
                            body = str(payload)
                        break
            else:
                payload = msg.get_payload(decode=True)
                if isinstance(payload, bytes):
                    body = payload.decode("utf-8", errors="ignore")
                else:
                    body = str(payload)

            # 打印调试信息（解码后的标题和纯邮箱）
            print(f"收到新邮件 - 标题: {subject}, 发件人: {from_email}")
            print(f"邮件正文: {body[:100]}...")

            # 处理邮件并传递 original_headers
            process_email(subject, body, from_email, cc_emails, original_headers)
            if message_id:
                save_processed_email(message_id)

    except imaplib.IMAP4.error as e:
        print(f"IMAP协议错误: {e}")
        raise  # 重新抛出异常，由 monitor_emails 处理
    except Exception as e:
        print(f"处理邮件时出错: {e}")

def monitor_emails(interval=1800):
    """
    定时监听邮箱
    :param interval: 监听间隔（秒）
    """
    print("开始监听邮箱...")
    mail = None
    try:
        while True:  # 添加外层循环以支持重连
            try:
                # 建立新的IMAP连接
                mail = imaplib.IMAP4_SSL(CONFIG["IMAP_SERVER"], CONFIG["IMAP_PORT"])
                mail.login(CONFIG["SENDER_EMAIL"], CONFIG["SENDER_PASSWORD"])
                print("邮箱连接已建立")
                
                # 处理邮件
                fetch_emails(mail)
                
                # 安全关闭连接
                if mail:
                    mail.logout()
                    mail = None
                    
            except imaplib.IMAP4.error as e:
                print(f"IMAP连接错误: {e}")
                # 如果连接出错，尝试关闭可能存在的连接
                if mail:
                    try:
                        mail.logout()
                    except:                      
                        pass     # 忽略退出时的异常
                    mail = None
                print("等待60秒后重新连接...")
                time.sleep(60)  # 等待60秒后重试
                continue  # 继续外层循环，重新连接
            except Exception as e:
                print(f"监听邮箱时出错: {e}")
                # 如果连接出错，尝试关闭可能存在的连接
                if mail:
                    try:
                        mail.logout()
                    except:
                        pass    # 忽略退出时的异常
                    mail = None
                print("等待60秒后重新连接...")
                time.sleep(60)  # 等待60秒后重试
                continue  # 继续外层循环，重新连接
                
            # 正常休眠
            print(f"等待 {interval} 秒后再次检查邮件...")
            time.sleep(interval)
            
    except KeyboardInterrupt:
        print("程序已手动终止")
    except Exception as e:
        print(f"监听邮箱时发生未处理的错误: {e}")
    finally:
        # 确保连接被关闭
        if mail:
            try:
                mail.logout()
                print("邮箱连接已关闭")
            except Exception as e:
                print(f"关闭邮箱连接时出错: {e}")

# ====================== 主程序入口 ======================
if __name__ == "__main__":
    logging.info("程序启动")
    try:
        monitor_emails()
    except KeyboardInterrupt:
        logging.info("程序被用户中断")
    except Exception as e:
        logging.error(f"程序发生未处理的异常: {e}")
        logging.error(f"异常详情: {traceback.format_exc()}")
        # 在窗口模式下等待用户按键，便于查看错误信息
        input("按回车键退出...")
    finally:
        logging.info("程序结束")
